package org.sampleSpringFramework.mvc.processor;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.sampleSpringFramework.mvc.render.ResultRender;
import org.sampleSpringFramework.mvc.render.impl.DefaultResultRender;
import org.sampleSpringFramework.mvc.render.impl.InternalErrorResultRender;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;

@Data
@Slf4j
public class RequestProcessorChain {

	/**
	 * 维护RequestProcessor的列表
	 */
	private Iterator<RequestProcessor> requestProcessorIterator;

	/**
	 * 请求
	 */
	private HttpServletRequest request;

	/**
	 * 响应
	 */
	private HttpServletResponse response;

	/**
	 * 请求方式
	 */
	private String requestMethod;

	/**
	 * 请求路径
	 */
	private String requestPath;

	/**
	 * 响应状态码
	 */
	private int responseCode;

	/**
	 * 结果渲染器
	 */
	private ResultRender resultRender;

	/**
	 * 构造函数
	 * @param iterator 请求处理器的迭代器，维护所有的RequestProcessor
	 * @param req 请求
	 * @param resp 响应
	 */
	public RequestProcessorChain(Iterator<RequestProcessor> iterator, HttpServletRequest req, HttpServletResponse resp) {
		this.requestProcessorIterator = iterator;
		this.request = req;
		this.response = resp;
		this.requestMethod = req.getMethod();
		this.requestPath = req.getPathInfo();
		this.responseCode = HttpServletResponse.SC_OK;//状态码默认设置为200
	}

	/**
	 * 执行责任链中的所有请求处理器RequestProcessor来处理请求
	 */
	public void doRequestProcessorChain() {
		try {
			// 1、遍历请求处理器列表
			while(requestProcessorIterator.hasNext()){
				// 2、执行责任链中的所有RequestProcessor，直到其中一个的方法返回为false时退出循环
				if(!requestProcessorIterator.next().process(this)) break;
			}
		} catch (Exception exception) {
			// 3、如果出现异常，交给自定义的异常Render处理
			this.resultRender = new InternalErrorResultRender(exception.getMessage());
			log.info("责任链执行过程中出现异常：InternalErrorResultRender");
		}
	}

	/**
	 *对处理的结果进行渲染
	 */
	public void doRender() {
		// 1、如果请求处理器实现类未选择Render渲染器，则选择默认的Render
		if(this.resultRender == null){
			this.resultRender = new DefaultResultRender();
		}
		// 2、执行Render方法
		try {
			this.resultRender.render(this);
		} catch (Exception exception) {
			log.error("对结果渲染的过程中出现异常",exception);
			throw new RuntimeException(exception);
		}
	}
}
